package model.readers.standard.xml;

import static model.readers.standard.xml.XmlReader.*;

import java.awt.Color;
import java.util.Stack;

import model.MetroModelBuilder;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

import com.nightpiter.controller.log.Logger;
import com.nightpiter.model.exceptions.TimeFormatException;
import com.nightpiter.model.objects.Time;

/**
 * This class handles events occurring in the SAX processing action
 * 
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
public class SaxEventsHandler extends DefaultHandler {

	private String version = null;

	private Stack<String> stack;

	private MetroModelBuilder modelBuilder;

	public SaxEventsHandler(MetroModelBuilder modelBuilder) {
		super();
		this.modelBuilder = modelBuilder;
		this.stack = new Stack<String>();
	}

	public void startDocument() {
	}

	public void endDocument() {
	}

	public void startElement(String uri, String qname, String name,
			Attributes attrs) {

		stack.push(name);
		String path = getPath();

		if (path.equals(ROOT + TUNNELS + TUNNEL)) {
			int from = Integer.parseInt(attrs.getValue(FROM_ATTR));
			int to = Integer.parseInt(attrs.getValue(TO_ATTR));
			int time = 0;
			boolean smooth = Boolean.parseBoolean(attrs.getValue(SMOOTH_ATTR));
			try {
				time = Time.stringToInt(attrs.getValue(TIME_ATTR));
			} catch (TimeFormatException e) {
			}
			int line = Integer.parseInt(attrs.getValue(LINE_ATTR));
			modelBuilder.addTunnel(to, from, time, line, smooth);

		} else if (path.equals(ROOT + STATIONS + STATION)) {
			int id = Integer.parseInt(attrs.getValue(ID_ATTR));
			modelBuilder.startStation(id);

		} else if (path.equals(ROOT + STATIONS + STATION + SCHEDULE)) {
			try {
				modelBuilder.setStationSchedule(new Time(attrs
						.getValue(OPEN_ATTR)), new Time(attrs
						.getValue(CLOSE_ATTR)));
			} catch (TimeFormatException e) {
				modelBuilder.setStationSchedule(new Time(0), new Time(0));
				e.printStackTrace();
			}

		} else if (path.equals(ROOT + STATIONS + STATION + NAME)) {
			try {
				int dx = Integer.parseInt(attrs.getValue(DX_ATTR));
				int dy = Integer.parseInt(attrs.getValue(DY_ATTR));
				int angle = Integer.parseInt(attrs.getValue(ANGLE_ATTR));
				boolean visible = Boolean.parseBoolean(attrs
						.getValue(VISIBLE_ATTR));
				modelBuilder.setStationNameAttrs(dx, dy, angle, visible);
			} catch (NumberFormatException e) {
				modelBuilder.setStationNameAttrs(0, 0, 0, false);
			}

		} else if (path.equals(ROOT + STATIONS + STATION + POSITION)) {
			int x = Integer.parseInt(attrs.getValue(X_ATTR));
			int y = Integer.parseInt(attrs.getValue(Y_ATTR));
			modelBuilder.setStationPosition(x, y);

		} else if (path.equals(ROOT + STATIONS + STATION + LOCATION)) {
			int latitude = Integer.parseInt(attrs.getValue(LATITUDE_ATTR));
			int longitude = Integer.parseInt(attrs.getValue(LONGITUDE_ATTR));
			modelBuilder.setStationLocation(latitude, longitude);

		} else if (path.equals(ROOT + TRANSFERS + TRANSFER)) {
			int from = Integer.parseInt(attrs.getValue(FROM_ATTR));
			int to = Integer.parseInt(attrs.getValue(TO_ATTR));
			int time = 0;
			try {
				time = Time.stringToInt(attrs.getValue(TIME_ATTR));
			} catch (TimeFormatException e) {
				e.printStackTrace();
			}
			modelBuilder.addTransfer(to, from, time);

		} else if (path.equals(ROOT + LINES + LINE)) {
			int id = Integer.parseInt(attrs.getValue(ID_ATTR));
			modelBuilder.startLine(id);
			try {
				modelBuilder.setLineColor(Color.decode(attrs
						.getValue(COLOR_ATTR)).getRGB());
			} catch (Exception e) {
				modelBuilder.setLineColor(Color.WHITE.getRGB());
			}

		} else if (path.equals(ROOT + STATIONS)) {
			modelBuilder.startStations();

		} else if (path.equals(ROOT + LINES)) {
			modelBuilder.startLines();

		} else if (path.equals(ROOT + TRANSFERS)) {
			modelBuilder.startTransfers();

		} else if (path.equals(ROOT + TUNNELS)) {
			modelBuilder.startTunnels();

		} else if (path.equals(ROOT)) {
			this.version = attrs.getValue(VERSION);
			Logger.log("xml file version retrieved: " + this.version);
			modelBuilder.startMap();
		}
	}

	public void endElement(String uri, String qname, String name) {

		String path = getPath();
		if (path.equals(ROOT + STATIONS + STATION)) {
			modelBuilder.endStation();

		} else if (path.equals(ROOT + LINES + LINE)) {
			modelBuilder.endLine();

		} else if (path.equals(ROOT + STATIONS)) {
			modelBuilder.endStations();

		} else if (path.equals(ROOT + LINES)) {
			modelBuilder.endLines();

		} else if (path.equals(ROOT + TRANSFERS)) {
			modelBuilder.endTransfers();

		} else if (path.equals(ROOT + TUNNELS)) {
			modelBuilder.endTunnels();

		} else if (path.equals(ROOT)) {
			modelBuilder.endMap();
		}

		stack.pop();
	}

	public void characters(char ch[], int start, int length) {
		String path = getPath();

		if (path.equals(ROOT + STATIONS + STATION + NAME)) {
			modelBuilder.setStationName(new String(ch, start, length).trim());

		} else if (path.equals(ROOT + LINES + LINE + NAME)) {
			modelBuilder.setLineName(new String(ch, start, length).trim());

		} else if (path.equals(ROOT + DESCRIPTION + CITY + NAME)) {
			modelBuilder.setCityName(new String(ch, start, length).trim());

		} else if (path.equals(ROOT + DESCRIPTION + NOTE)) {
			modelBuilder.setNote(new String(ch, start, length).trim());

		} else if (path.equals(ROOT + DESCRIPTION + AUTHORS + AUTHOR + NAME)) {
			modelBuilder.setAuthorName(new String(ch, start, length).trim());

		}
	}

	private String getPath() {
		String path = "";
		for (int i = 0; i < stack.size(); i++) {
			path += stack.get(i);
		}
		return path;
	}

}
